package com.easylinkin.linkappapi.quality.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.quality.dto.ProblemTypeDTO;
import com.easylinkin.linkappapi.quality.entity.Problem;
import com.easylinkin.linkappapi.quality.entity.ProblemType;
import com.easylinkin.linkappapi.quality.mapper.ProblemMapper;
import com.easylinkin.linkappapi.quality.mapper.ProblemTypeMapper;
import com.easylinkin.linkappapi.quality.service.ProblemTypeService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 闸机表 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2022-04-13
 */
@Service
@Slf4j
public class ProblemTypeServiceImpl extends ServiceImpl<ProblemTypeMapper, ProblemType> implements
    ProblemTypeService {

  @Resource
  private LinkappUserContextProducer linkappUserContextProducer;

  @Autowired
  private ProblemMapper problemMapper;

  /**
   * 增加
   * @param problemType
   */
  @Override
  public void insert(ProblemType problemType) {
    /**
     * 验证重复
     */
    this.checkExist(problemType);
    //设置基本属性
    this.setBase(problemType);
    this.save(problemType);
  }

  @Override
  public void addFromEnterprise(ProblemType problemType) {
    log.info("来自企业端的新增");
    validParamRequired(problemType);
    // 设置fullName （已沟通，fullId 可都留空）
    if (problemType.getParentId().equals(0)) {
      problemType.setFullName(problemType.getName());
      problemType.setLevel(1);
    } else {
      ProblemType parent = this.getById(problemType.getParentId());
      Assert.notNull(parent, "查询隐患父节点为空");
      problemType.setFullName(parent.getFullName() + "/" + problemType.getName());
      problemType.setLevel(parent.getLevel() + 1);
      Assert.isTrue(problemType.getLevel() < 3, "问题类别不能超过两级");
    }
    validParamFormat(problemType);
    validRepeat(problemType);

    Calendar calendar = Calendar.getInstance();
    problemType.setCreateTime(calendar.getTime());
    problemType.setModifyTime(calendar.getTime());
    save(problemType);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void updateFromEnterprise(ProblemType problemType) {
    ProblemType old = this.getById(problemType.getId());
    Assert.isTrue(old != null, "根据ID查询不存在");



    ProblemType parent = this.getById(old.getParentId());
    String newNameBefore = null;
    if (parent!=null) {
      newNameBefore = parent.getFullName() + "/" + problemType.getName();
      problemType.setFullName(newNameBefore);
    } else {
      newNameBefore = problemType.getName();
      problemType.setFullName(problemType.getName());
    }
    validParamFormat(problemType);
    validRepeat(problemType);

    if (!Objects.equals(old.getName(), problemType.getName())) {
      // 所有隐患描述的fullname 需要修改
      problemMapper.updateByTypeNameChange(old.getFullName(), old.getFullName().length(), newNameBefore);
      // 所有子类型的fullname 需要修改
      if (old.getParentId() != null && old.getParentId().equals(0)) {
        baseMapper.updateByTypeNameChange(old.getId(), old.getFullName().length(), newNameBefore);
      }
    }


    problemType.setModifyTime(new Date());
    UpdateChainWrapper<ProblemType> updateWrapper = new UpdateChainWrapper<>(baseMapper);
    updateWrapper.eq("id", problemType.getId());
    updateWrapper.update(problemType);

  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void deleteFromEnterprise(ProblemType problemType) {
    Integer id = problemType.getId();
    // 级联删除 其下面的 隐患描述
    // 级联删除 其下面的 子类别
    ProblemType old = this.getById(id);
    String fullName = old.getFullName();
    problemMapper.deleteByTypeFullName(fullName);

    //删除 其下面的子类型
    if (old.getParentId() != null && old.getParentId().equals(0)) {
      QueryWrapper<ProblemType> queryWrapper = new QueryWrapper();
      queryWrapper.eq("parent_id_", problemType.getId());
      queryWrapper.isNull("tenant_id_");
      baseMapper.delete(queryWrapper);
    }
    baseMapper.deleteById(id);
  }



  /**
   * 模板-校验重复
   */
  private void validRepeat(ProblemType problemType) {
    QueryWrapper<ProblemType> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("full_name_", problemType.getFullName());
    queryWrapper.isNull("tenant_id_");
    List<ProblemType> list = baseMapper.selectList(queryWrapper);
    if (list.size() == 0) {
      return;
    }
    if (list.size() > 1) {
      throw new BusinessException("名称有重复");
    }
    if (ObjectUtils.isEmpty(problemType.getId())) {
      throw new BusinessException("名称已存在");
    }
    if (!problemType.getId().equals(list.get(0).getId())) {
      throw new BusinessException("名称已存在");
    }
  }


  /**
   * 校验参数必填
   */
  private void validParamRequired(ProblemType problemType) {
    Assert.notNull(problemType, "参数为空");
    Assert.isTrue(ObjectUtils.isNotEmpty(problemType.getName()), "名称为空");
    Assert.isTrue(ObjectUtils.isNotEmpty(problemType.getParentId()), "父id为空");
  }

  /**
   * 校验参数格式
   */
  private void validParamFormat(ProblemType problemType) {
    Assert.isTrue(problemType.getName() == null || problemType.getName().length() <= 128,
            "名称超长");
  }

  /**
   * 根据id编辑
   * @param problemType
   */
  @Override
  public void updateOne(ProblemType problemType) {
    /**
     * 验证重复
     */
    this.checkExist(problemType);
    //设置基本属性
    this.setBase(problemType);
    this.updateById(problemType);
  }

  /**
   * @Description: 根据条件，查询
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @Override
  public List<ProblemTypeDTO> queryList(ProblemType problemType) {
    List<ProblemTypeDTO> problemTypeDTOS;
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //查询默认的(tenantId为null) 和本项目的
    QueryWrapper<ProblemType> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_",tenantId)
        .orderByAsc("id");
    List<ProblemType> problemTypes = baseMapper.selectList(queryWrapper);
    //筛选第一级节点
    List<ProblemType> problemTypeList = problemTypes.stream()
        .filter(p -> Integer.valueOf(0).equals(p.getParentId()))
        .collect(Collectors.toList());
    //二级节点
    problemTypes.removeAll(problemTypeList);
    //查找问题库
    Set<Integer> ids = problemTypes.stream().map(p -> p.getId()).collect(Collectors.toSet());
    QueryWrapper<Problem> problemQueryWrapper = new QueryWrapper<>();
    problemQueryWrapper.in("problem_type_id_",ids);
    List<Problem> problems = problemMapper.selectList(problemQueryWrapper);
    List<ProblemTypeDTO> sonTypeDTOS = BeanUtil.copyToList(problemTypes, ProblemTypeDTO.class);
    //二级数量
    sonTypeDTOS.forEach(p->{
      long count = problems.stream().filter(pr -> p.getId().equals(pr.getProblemTypeId()))
          .count();
      p.setCount((int)count);
    });
    problemTypeDTOS = BeanUtil.copyToList(problemTypeList, ProblemTypeDTO.class);
    problemTypeDTOS.forEach(p ->{
      List<ProblemTypeDTO> dtos = sonTypeDTOS.stream()
          .filter(s -> p.getId().equals(s.getParentId()))
          .collect(Collectors.toList());
      p.setSonList(dtos);
    });
    return problemTypeDTOS;
  }

  @Override
  public List<ProblemTypeDTO> listFromEnterprise(ProblemType problemType) {
    List<ProblemTypeDTO> problemTypeDTOS;
    QueryWrapper<ProblemType> queryWrapper = new QueryWrapper<>();
    queryWrapper.isNull("tenant_id_")
            .orderByDesc("create_time_");
    List<ProblemType> problemTypes = baseMapper.selectList(queryWrapper);
    // 筛选第一级节点
    List<ProblemType> problemTypeList = problemTypes.stream()
            .filter(p -> Integer.valueOf(0).equals(p.getParentId()))
            .collect(Collectors.toList());
    //二级节点
    problemTypes.removeAll(problemTypeList);
    //查找问题库
    Set<Integer> ids = problemTypes.stream().map(p -> p.getId()).collect(Collectors.toSet());
    QueryWrapper<Problem> problemQueryWrapper = new QueryWrapper<>();
    problemQueryWrapper.in("problem_type_id_", ids);
    List<Problem> problems = problemMapper.selectList(problemQueryWrapper);
    List<ProblemTypeDTO> sonTypeDTOS = BeanUtil.copyToList(problemTypes, ProblemTypeDTO.class);
    //二级数量
    sonTypeDTOS.forEach(p -> {
      long count = problems.stream().filter(pr -> p.getId().equals(pr.getProblemTypeId()))
              .count();
      p.setCount((int) count);
    });
    problemTypeDTOS = BeanUtil.copyToList(problemTypeList, ProblemTypeDTO.class);
    problemTypeDTOS.forEach(p -> {
      List<ProblemTypeDTO> dtos = sonTypeDTOS.stream()
              .filter(s -> p.getId().equals(s.getParentId()))
              .collect(Collectors.toList());
      p.setSonList(dtos);
      p.setCount(dtos.stream().mapToInt(ProblemTypeDTO::getCount).sum());
    });
    return problemTypeDTOS;
  }

  /**
   * @Description: 查询问题树(下拉选择使用)
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @Override
  public List<ProblemTypeDTO> queryTree() {
    List<ProblemTypeDTO> problemTypeDTOS;
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //查询默认的(tenantId为null) 和本项目的
    QueryWrapper<ProblemType> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_",tenantId)
        .orderByAsc("id");
    List<ProblemType> problemTypes = baseMapper.selectList(queryWrapper);
    //筛选第一级节点
    List<ProblemType> problemTypeList = problemTypes.stream()
        .filter(p -> Integer.valueOf(0).equals(p.getParentId()))
        .collect(Collectors.toList());
    //二级节点
    problemTypes.removeAll(problemTypeList);
    //查找问题库
    Set<Integer> ids = problemTypes.stream().map(p -> p.getId()).collect(Collectors.toSet());
    QueryWrapper<Problem> problemQueryWrapper = new QueryWrapper<>();
    problemQueryWrapper.in("problem_type_id_",ids)
        .eq("disable_",1)
        .orderByAsc("order_");
    List<Problem> problems = problemMapper.selectList(problemQueryWrapper);
    List<ProblemTypeDTO> sonTypeDTOS = BeanUtil.copyToList(problemTypes, ProblemTypeDTO.class);
    //二级数量
    sonTypeDTOS.forEach(p->{
      List<Problem> problemList = problems.stream()
          .filter(pr -> p.getId().equals(pr.getProblemTypeId())).collect(Collectors.toList());
      if (problemList.size()> 0){
        List<ProblemTypeDTO> sonList = new ArrayList<>();
        problemList.forEach(sp ->{
          ProblemTypeDTO problemTypeDTO = new ProblemTypeDTO();
          problemTypeDTO.setId(sp.getId());
          problemTypeDTO.setName(sp.getContent());
          problemTypeDTO.setFullName(sp.getFullName());
          problemTypeDTO.setParentId(sp.getProblemTypeId());
          problemTypeDTO.setLevel(3);
          problemTypeDTO.setProblemLevel(sp.getLevel());
          problemTypeDTO.setChangeLimit(sp.getChangeLimit());
          problemTypeDTO.setChangeRequirement(sp.getChangeRequirement());
          sonList.add(problemTypeDTO);
        });
        p.setSonList(sonList);
      }
    });
    problemTypeDTOS = BeanUtil.copyToList(problemTypeList, ProblemTypeDTO.class);
    problemTypeDTOS.forEach(p ->{
      List<ProblemTypeDTO> dtos = sonTypeDTOS.stream()
          .filter(s -> p.getId().equals(s.getParentId()))
          .collect(Collectors.toList());
      p.setSonList(dtos);
    });
    return problemTypeDTOS;
  }

  @Override
  public IPage<ProblemType> queryListByPage(RequestModel<ProblemType> requestModel) {
    Page page = requestModel.getPage();
    ProblemType problemType = requestModel.getCustomQueryParams();
    //项目id 过滤
    problemType.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    IPage<ProblemType> problemTypeIPage = baseMapper.queryListByPage(page, problemType);
    return problemTypeIPage;
  }

  /**
   * 验证重复
   */
  private void checkExist(ProblemType problemType) {
    QueryWrapper<ProblemType> queryWrapper = new QueryWrapper<>();
    //todo 设置判断重复条件
    //编辑的时候存在id
    Optional.ofNullable(problemType.getId()).ifPresent(id -> queryWrapper.ne("id_",problemType.getId()));
    Integer integer = baseMapper.selectCount(queryWrapper);
    if (integer>0){
      throw new BusinessException("该闸机已存在");
    }
  }

  /**
   * 设置基本属性
   * @param problemType
   */
  private void setBase(ProblemType problemType) {
    problemType.setModifyTime(new Date());
    problemType.setModifyId(linkappUserContextProducer.getCurrent().getId());
    //没有id就是新增,有就是编辑
    if (null == problemType.getId()){
      problemType.setCreatorId(linkappUserContextProducer.getCurrent().getId());
      problemType.setCreateTime(new Date());
      problemType.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    }
  }



}
